/**
 * @filename:SaleOutStockServiceImpl Feb 18, 2025
 * @project Wonder Vue Admin Api  1.1.0
 * Copyright(c) 2022 Wonder Co. Ltd. 
 * All right reserved. 
 */
package com.wonder.app.service.impl;

import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.utils.VtuzxUtil;
import com.wonder.admin.service.IVtuzxKingdeeService;
import com.wonder.app.domain.*;
import com.wonder.app.mapper.SaleOutStockDao;
import com.wonder.app.mapper.SaleOutStockDetailDao;
import com.wonder.app.service.*;
import com.wonder.app.request.SaleOutStockRequest;
import com.wonder.bean.kingdee.VtuzxKingdeeCloudClient;
import com.wonder.bean.kingdee.xqc.VtuzxArrayList;
import com.wonder.common.common.AjaxMap;
import com.wonder.common.utils.StringUtils;
import com.wonder.common.utils.MessageUtils;
import com.wonder.common.common.AjaxResult;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
//import com.wonder.utils.DateUtils;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description:TODO(销售出库单服务实现)
 *
 * @version: 1.1.0
 * @author: Wonder
 * 
 */
@Service
public class SaleOutStockServiceImpl  extends ServiceImpl<SaleOutStockDao, SaleOutStock> implements SaleOutStockService  {
	/** 日志 */
	private static final Logger _logger = LoggerFactory.getLogger(SfcOperpServiceImpl.class);

	@Autowired
	private SaleOutStockService saleOutStockService;
	@Autowired
	private SaleOutStockDao saleOutStockDao;
	@Autowired
	private SaleOutStockDetailService saleOutStockDetailService;
	@Autowired
	private SaleOutStockDetailDao saleOutStockDetailDao;
	@Autowired
	private IVtuzxKingdeeService vtuzxKingdeeService;
	@Autowired
	private SyncKingdeeOrderService syncKingdeeOrderService;
	@Autowired
	private SyncOrderService syncOrderService;
	@Autowired
	private  MaterialService materialService;
    /**
     * 验证销售出库单信息
     *
     * @param saleOutStock
     * @param type
     * @return String
     */
    @Override
    public String validate(SaleOutStock saleOutStock,String type){


       return "";
    }


    /**
	 * Description:销售出库单分页返回
	 * @param request //检索条件
	 * @param page //分页参数
	 * @return IPage<SaleOutStock>   //分页记录
	 */
	@Override
	public IPage<SaleOutStock> selectList(SaleOutStockRequest request, Page<SaleOutStock> page){
	    LambdaQueryWrapper<SaleOutStock> lambdaQueryWrapper = new LambdaQueryWrapper<>();

	    if (null != request.getId()) {
	       lambdaQueryWrapper.eq(SaleOutStock::getId, request.getId());
	      }

		if (request.getIsDate() != null) {
			Date[] fCREATEDATE = request.getIsDate();
			if (fCREATEDATE.length > 0) {
				// 设置开始时间为当天的零点
				Calendar startCalendar = Calendar.getInstance();
				startCalendar.setTime(fCREATEDATE[0]);
				startCalendar.set(Calendar.HOUR_OF_DAY, 0);
				startCalendar.set(Calendar.MINUTE, 0);
				startCalendar.set(Calendar.SECOND, 0);
				startCalendar.set(Calendar.MILLISECOND, 0);
				Date startDate = startCalendar.getTime();
				lambdaQueryWrapper.ge(SaleOutStock::getIsDate, startDate);
			}
			if (fCREATEDATE.length == 2) {
				// 设置结束时间为当天的24点
				Calendar endCalendar = Calendar.getInstance();
				endCalendar.setTime(fCREATEDATE[1]);
				endCalendar.set(Calendar.HOUR_OF_DAY, 23);
				endCalendar.set(Calendar.MINUTE, 59);
				endCalendar.set(Calendar.SECOND, 59);
				endCalendar.set(Calendar.MILLISECOND, 999);
				Date endDate = endCalendar.getTime();
				lambdaQueryWrapper.le(SaleOutStock::getIsDate, endDate);
			}
		}

		if (StringUtils.hasText(request.getBillNo())) {
			lambdaQueryWrapper.like(SaleOutStock::getBillNo, request.getBillNo());
		}

		if (StringUtils.hasText(request.getCustNo())) {
			lambdaQueryWrapper.like(SaleOutStock::getCustNo, request.getCustNo());
		}

		lambdaQueryWrapper.orderByDesc(SaleOutStock::getId);
		Page<SaleOutStock> selectPage = this.baseMapper.selectPage(page, lambdaQueryWrapper);
		return selectPage;
    }

	/**
	 *
	 * 导入
	 */
	@Override
	public AjaxResult<Object> importData(List<Map<String, Object>> map) {
		if (map == null || map.size()==0){ return AjaxResult.failed(MessageUtils.message("import.file.no.data"));}
		List<SaleOutStock> list = new ArrayList<>();
		List<SaleOutStockDetail> saleOutStockDetailList = new ArrayList<>();
		String billNo = "";
		SaleOutStock saleOutStock = new SaleOutStock();

		String lastBoxNo = null;

		if (map.size() < 1) {
			return AjaxResult.failed("数据格式错误，缺少主表信息");
		}
				Map<String, Object> headerRow = map.get(0); // 修正为索引1
				if (headerRow == null) {
					return AjaxResult.failed("第二行数据为空");
				}
				System.out.println("Header Row Keys: " + headerRow.keySet());
				// 提取确认日期（B列）
		if (headerRow.containsKey("__EMPTY_1")) {
			Object dateValue = headerRow.get("__EMPTY_1");

			if (dateValue instanceof Number) {
				double excelDateValue = ((Number) dateValue).doubleValue();
				Date date = convertExcelDateToJavaDate(excelDateValue);
				// 清除时间部分
				date = removeTimeFromDate(date);
				saleOutStock.setIsDate(date);
			} else if (dateValue instanceof String) {
				try {
					SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d");
					Date date = dateFormat.parse(dateValue.toString());
					// 清除时间部分（虽然解析后可能已为零点，但确保一致）
					date = removeTimeFromDate(date);
					saleOutStock.setIsDate(date);
				} catch (ParseException e) {
					System.err.println("日期解析失败: " + dateValue);
				}
			} else {
				System.err.println("未知的日期格式: " + dateValue);
			}
		}
		// 新增：为 Diffent 字段赋固定值 "天"
		saleOutStock.setDiffent("周"); // 调用 setDiffent() 方法
				// 提取客户编号（H列）
				if (headerRow.containsKey("__EMPTY_8")) {
					saleOutStock.setCustNo(headerRow.get("__EMPTY_8").toString());
				}

				// 提取订单号（F列）
				if (headerRow.containsKey("__EMPTY_5")) {
					saleOutStock.setBillNo(headerRow.get("__EMPTY_5").toString());
					billNo = headerRow.get("__EMPTY_5").toString();
					String checkresult = checkSaleOutStock(billNo);
					if (checkresult != "1"){
						return AjaxResult.failed(MessageUtils.message(checkresult));
					}

				}

				list.add(saleOutStock);
// 提取明细数据（第三行及之后）
			for (int i = 2; i < map.size(); i++) {
				Map<String, Object> row = map.get(i);
				SaleOutStockDetail detail = new SaleOutStockDetail();
				String currentBillNo = "";
				// 根据表头映射字段，示例：
				if (row.containsKey("__EMPTY_4")) detail.setNTKNO(row.get("__EMPTY_4").toString()); // NTK NO.
				// 检查订单号是否为空，若为空则停止循环
				if (row.containsKey("包装作业核对表")) {
					Object billNoObj = row.get("包装作业核对表");
					currentBillNo = (billNoObj != null) ? billNoObj.toString().trim() : "";
				}
				if (currentBillNo.isEmpty()) {
					break; // 订单号为空，终止循环
				}
				// 处理合并单元格逻辑（C列箱号）

				if (row.containsKey("__EMPTY_1")) {
					String currentBoxNo = row.get("__EMPTY_1").toString().trim();
					if (!currentBoxNo.isEmpty()) {
						lastBoxNo = currentBoxNo; // 更新箱号
					}
				}
				// 继承上一个非空箱号
				detail.setBoxNo(lastBoxNo != null ? lastBoxNo : "");
				if (row.containsKey("__EMPTY_2")) detail.setCustNumber(row.get("__EMPTY_2").toString()); // 客户件号
				if (row.containsKey("__EMPTY_3")) detail.setEngerNumber(row.get("__EMPTY_3").toString()); // 工程件号
				if (row.containsKey("__EMPTY_4")) detail.setTYNumber(row.get("__EMPTY_4").toString()); // TY件号
				if (row.containsKey("__EMPTY_5")) detail.setStockNumber(row.get("__EMPTY_5").toString()); // 库存货位
				if (row.containsKey("__EMPTY_6"))
					detail.setCount(Double.parseDouble(row.get("__EMPTY_6").toString())); // 数量
				if (row.containsKey("__EMPTY_7")) {
					String valueStr = row.get("__EMPTY_7").toString();
					try {
						// 直接解析字符串为BigDecimal，避免double转换的精度损失
						BigDecimal bd = new BigDecimal(valueStr);
						// 四舍五入保留两位小数
						bd = bd.setScale(2, RoundingMode.HALF_UP);
						detail.setSingleWeight(bd.doubleValue());
					} catch (NumberFormatException e) {
						detail.setSingleWeight(0.0); // 解析失败时设置默认值
					}
				}// 单重
				if (row.containsKey("__EMPTY_8")) {
				String valueStr = row.get("__EMPTY_8").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setNetWeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setNetWeight(0.0); // 解析失败时设置默认值
				}
			}// 净重
				if (row.containsKey("__EMPTY_9")) {
					String valueStr = row.get("__EMPTY_9").toString();
					try {
						// 直接解析字符串为BigDecimal，避免double转换的精度损失
						BigDecimal bd = new BigDecimal(valueStr);
						// 四舍五入保留两位小数
						bd = bd.setScale(2, RoundingMode.HALF_UP);
						detail.setGrossWeight(bd.doubleValue());
					} catch (NumberFormatException e) {
						detail.setGrossWeight(0.0); // 解析失败时设置默认值
					}
				}// 毛重
//				if (row.containsKey("__EMPTY_10")) detail.setIsPressure(row.get("__EMPTY_10").toString()); // 是否可叠压
				if (row.containsKey("__EMPTY_10")) {
					Object pressureValue = row.get("__EMPTY_10");
					if (pressureValue != null) {
						try {
							double numValue = Double.parseDouble(pressureValue.toString());
							detail.setIsPressure(numValue == 0.5 ? "是" : "否");
						} catch (NumberFormatException e) {
							detail.setIsPressure("否");
						}
					} else {
						detail.setIsPressure("否");
					}
				} else {
					detail.setIsPressure("否");
				}

				if (row.containsKey("__EMPTY_11")) {
					String valueStr = row.get("__EMPTY_11").toString();
					try {
						// 直接解析字符串为BigDecimal，避免double转换的精度损失
						BigDecimal bd = new BigDecimal(valueStr);
						// 四舍五入保留两位小数
						bd = bd.setScale(2, RoundingMode.HALF_UP);
						detail.setLongth(bd.doubleValue());
					} catch (NumberFormatException e) {
						detail.setLongth(0.0); // 解析失败时设置默认值
					}
				}//长
				if (row.containsKey("__EMPTY_13")) {
					String valueStr = row.get("__EMPTY_13").toString();
					try {
						// 直接解析字符串为BigDecimal，避免double转换的精度损失
						BigDecimal bd = new BigDecimal(valueStr);
						// 四舍五入保留两位小数
						bd = bd.setScale(2, RoundingMode.HALF_UP);
						detail.setWidth(bd.doubleValue());
					} catch (NumberFormatException e) {
						detail.setWidth(0.0); // 解析失败时设置默认值
					}
				}//宽
				if (row.containsKey("__EMPTY_15")) {
					String valueStr = row.get("__EMPTY_15").toString();
					try {
						// 直接解析字符串为BigDecimal，避免double转换的精度损失
						BigDecimal bd = new BigDecimal(valueStr);
						// 四舍五入保留两位小数
						bd = bd.setScale(2, RoundingMode.HALF_UP);
						detail.setHeight(bd.doubleValue());
					} catch (NumberFormatException e) {
						detail.setHeight(0.0); // 解析失败时设置默认值
					}
				}//高

				if (row.containsKey("__EMPTY_16")) detail.setBarCode(row.get("__EMPTY_16").toString()); // 条码
				// 2. 映射计划出货日期（列 Q）
				if (row.containsKey("__EMPTY_17")) {
					Object dateValue = row.get("__EMPTY_17");

					if (dateValue instanceof Number) {
						double excelDateValue = ((Number) dateValue).doubleValue();
						Date date = convertExcelDateToJavaDate(excelDateValue);
						// 清除时间部分
						date = removeTimeFromDate(date);
						detail.setOutTime(date);
					} else if (dateValue instanceof String) {
						try {
							SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d");
							Date date = dateFormat.parse(dateValue.toString());
							// 清除时间部分（虽然解析后可能已为零点，但确保一致）
							date = removeTimeFromDate(date);
							detail.setOutTime(date);
						} catch (ParseException e) {
							System.err.println("日期解析失败: " + dateValue);
						}
					} else {
						System.err.println("未知的日期格式: " + dateValue);
					}
				}
				//TY净重四舍五入
				if (row.containsKey("__EMPTY_20")) {
					String valueStr = row.get("__EMPTY_20").toString();
					try {
						double rawValue = Double.parseDouble(valueStr);
						long roundedValue = Math.round(rawValue); // 四舍五入到整数
						detail.setTYNetWeight((double) roundedValue); // 根据字段类型调整
					} catch (NumberFormatException e) {
						detail.setTYNetWeight(0.0); // 处理无效数据
					}
				}
				if (row.containsKey("__EMPTY_21"))
					detail.setTYParper(Double.parseDouble(row.get("__EMPTY_21").toString())); // TY纸盒   为空有问题

				if (row.containsKey("__EMPTY_22"))
					detail.setTYPalletHelp(Double.parseDouble(row.get("__EMPTY_22").toString())); // TY托盘+辅助
				if (row.containsKey("__EMPTY_23"))
					detail.setTYGroWeight(Double.parseDouble(row.get("__EMPTY_23").toString())); // TY毛重
				// 其他字段映射...

				// 关联主表
				detail.setBillNo(billNo);
				saleOutStockDetailList.add(detail);
			}

		boolean ret = saleOutStockService.saveBatch(list);
		boolean detailret = saleOutStockDetailService.saveBatch(saleOutStockDetailList);
		if(ret & detailret)
			return AjaxResult.success();
		else {
			return AjaxResult.failed(MessageUtils.message("import.failed"));
		}

	}//判断订单是否存在
	public String checkSaleOutStock(String billNo) {
		QueryWrapper<SaleOutStock> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("billno", billNo); // 明确指定数据库列名
		SaleOutStock existing = saleOutStockDao.selectOne(queryWrapper);
		return existing != null ? String.format("订单 %s 已存在", billNo) : "1";
	}
	//日期转换
	public static Date convertExcelDateToJavaDate(double excelDateValue) {
		// Excel 的日期起点是 1900-01-01，Java 的日期起点是 1970-01-01
		// 需要计算两者之间的天数差
		long daysSince1900 = (long) excelDateValue;
		long daysSince1970 = daysSince1900 - 25569; // 25569 是 1900-01-01 到 1970-01-01 的天数
		long millisecondsSince1970 = daysSince1970 * 24 * 60 * 60 * 1000;

		// 创建 Date 对象
		return new Date(millisecondsSince1970);
	}
	// 辅助方法：去除时间部分
	private Date removeTimeFromDate(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		// 将时、分、秒、毫秒设置为0
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}
	/**
	 * 导入
	 */
	@Override
	public AjaxResult<Object> importAData(List<Map<String, Object>> map) {
		if (map == null || map.size()==0){ return AjaxResult.failed(MessageUtils.message("import.file.no.data"));}
// 1. 提取所有明细中的订单号（假设订单号在列O，对应 __EMPTY_15）
		Set<String> billNoSet = new HashSet<>();
		List<SaleOutStockDetail> detailList = new ArrayList<>();
		String lastBoxNo = null;
		for (int i = 2; i < map.size(); i++) {
			Map<String, Object> row = map.get(i);
			String detailBillNo = row.getOrDefault("__EMPTY_15", "").toString().trim();
			if (detailBillNo.isEmpty()) {
				// 可选：记录错误或跳过空订单号的行
				break;
			}
			// 记录唯一订单号
			billNoSet.add(detailBillNo);
			// 处理明细数据
			SaleOutStockDetail detail = new SaleOutStockDetail();
			detail.setBillNo(detailBillNo);

			// 根据表头映射字段，示例：
			if (row.containsKey("__EMPTY")) detail.setNote(row.get("__EMPTY").toString()); // 备注
			// 处理合并单元格逻辑（C列箱号）
			if (row.containsKey("包装作业核对表")) {
				String currentBoxNo = row.get("包装作业核对表").toString().trim();
				if (!currentBoxNo.isEmpty()) {
					lastBoxNo = currentBoxNo; // 更新箱号
				}
			}
			// 继承上一个非空箱号
			detail.setBoxNo(lastBoxNo != null ? lastBoxNo : "");
			if (row.containsKey("__EMPTY_1")) detail.setCustNumber(row.get("__EMPTY_1").toString()); //客户件号
			if (row.containsKey("__EMPTY_2")) detail.setNTKNO(row.get("__EMPTY_2").toString()); //NTK No.
			if (row.containsKey("__EMPTY_3")) detail.setSKU(row.get("__EMPTY_3").toString()); //SKU

			if (row.containsKey("__EMPTY_4"))
				detail.setCount(Double.parseDouble(row.get("__EMPTY_4").toString())); //数量

			if (row.containsKey("__EMPTY_20")) {
				String valueStr = row.get("__EMPTY_20").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setSingleWeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setSingleWeight(0.0); // 解析失败时设置默认值
				}
			}//单重

			if (row.containsKey("__EMPTY_5")) detail.setPalletsNumber(row.get("__EMPTY_5").toString()); //拖数
			if (row.containsKey("__EMPTY_6"))
				detail.setNetWeight(Double.parseDouble(row.get("__EMPTY_6").toString())); //净重
			if (row.containsKey("__EMPTY_8"))
				detail.setGrossWeight(Double.parseDouble(row.get("__EMPTY_8").toString())); //毛重
			if (row.containsKey("__EMPTY_10")) {
				String valueStr = row.get("__EMPTY_10").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setLongth(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setLongth(0.0); // 解析失败时设置默认值
				}
			}//长
			if (row.containsKey("__EMPTY_12")) {
				String valueStr = row.get("__EMPTY_12").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setWidth(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setWidth(0.0); // 解析失败时设置默认值
				}
			}//宽
			if (row.containsKey("__EMPTY_14")) {
				String valueStr = row.get("__EMPTY_14").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setHeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setHeight(0.0); // 解析失败时设置默认值
				}
			}//高

			if (row.containsKey("__EMPTY_16")) detail.setTYNumber(row.get("__EMPTY_16").toString()); // TY件号
//			if (row.containsKey("__EMPTY_17")) detail.setCustNumber(row.get("__EMPTY_17").toString()); // 客户件号
			if (row.containsKey("__EMPTY_18")) detail.setBarCode(row.get("__EMPTY_18").toString()); //条形码内容
			if (row.containsKey("__EMPTY_19")) detail.setAimPort(row.get("__EMPTY_19").toString()); // 目的港
			// 2. 映射计划出货日期（列 Q）
			if (row.containsKey("__EMPTY_21")) {
				Object dateValue = row.get("__EMPTY_21");

				if (dateValue instanceof Number) {
					double excelDateValue = ((Number) dateValue).doubleValue();
					Date outTime = convertExcelDateToJavaDate(excelDateValue);
					// 清除时间部分（强制归零）
					outTime = removeTimeFromDate(outTime);
					detail.setOutTime(outTime);
				} else if (dateValue instanceof String) {
					try {
						SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d");
						Date outTime = dateFormat.parse(dateValue.toString());
						// 即使字符串没有时间，仍强制清除时间部分
						outTime = removeTimeFromDate(outTime);
						detail.setOutTime(outTime);
					} catch (ParseException e) {
						System.err.println("日期解析失败: " + dateValue);
					}
				} else {
					System.err.println("未知的日期格式: " + dateValue);
				}
			}
			detailList.add(detail);
		}

			// 2. 动态生成主表记录（每个BillNo一个主表）
			List<SaleOutStock> mainList = new ArrayList<>();
		Map<String, Object> headerRow = map.get(0); // 标题行
			for (String billNo : billNoSet) {
				SaleOutStock saleOutStock = new SaleOutStock();
				saleOutStock.setBillNo(billNo);
				System.out.println("Header Row Keys: " + headerRow.keySet());
                // 新增：为 Diffent 字段赋固定值 "天"
					saleOutStock.setDiffent("周"); // 调用 setDiffent() 方法
				// 提取确认日期（B列）
				if (headerRow.containsKey("__EMPTY_1")) {
					Object dateValue = headerRow.get("__EMPTY_1");

					if (dateValue instanceof Number) {
						double excelDateValue = ((Number) dateValue).doubleValue();
						Date date = convertExcelDateToJavaDate(excelDateValue);
						// 清除时间部分
						date = removeTimeFromDate(date);
						saleOutStock.setIsDate(date);
					} else if (dateValue instanceof String) {
						try {
							SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d");
							Date date = dateFormat.parse(dateValue.toString());
							// 清除时间部分（虽然解析后可能已为零点，但确保一致）
							date = removeTimeFromDate(date);
							saleOutStock.setIsDate(date);
						} catch (ParseException e) {
							System.err.println("日期解析失败: " + dateValue);
						}
					} else {
						System.err.println("未知的日期格式: " + dateValue);
					}
				}
				// 提取客户编号（H列）
				if (headerRow.containsKey("__EMPTY_11")) {
					String custNo = headerRow.get("__EMPTY_11").toString().replace("客户：", "").trim();
					if (custNo.isEmpty()) {
						return AjaxResult.failed("客户编号为空");
					}
					saleOutStock.setCustNo(custNo);
				}
				// 检查订单号是否有效
				String checkResult = checkSaleOutStock(billNo);
				if (!"1".equals(checkResult)) {
					return AjaxResult.failed(MessageUtils.message(checkResult));
				}

				mainList.add(saleOutStock);
			}

		boolean ret = saleOutStockService.saveBatch(mainList);
		boolean detailret = saleOutStockDetailService.saveBatch(detailList);
		if(ret & detailret)
			return AjaxResult.success();
		else {
			return AjaxResult.failed(MessageUtils.message("import.failed"));
		}

	}

	/**
	 * 导入发货明细AZO明细
	 */
	@Override
	public AjaxResult<Object> importAdData(String userName,Long user_id,List<Map<String, Object>> map) throws Exception{
		if (map == null || map.size()==0){ return AjaxResult.failed(MessageUtils.message("没有获取到数据，请检查模板sheet页"));}
// 1. 提取所有明细中的订单号（假设订单号在列O，对应 __EMPTY_15）
		// 获取第二行的列头信息（索引为1）
		try {
			Map<String, Object> headRow = map.get(1);
			String khHeader = String.valueOf(headRow.get("__EMPTY")).trim();
			String rqHeader = String.valueOf(headRow.get("__EMPTY_9")).trim();
		   Map<String, Object> skuRow = map.get(2);
			String ddbody = String.valueOf(skuRow.get("__EMPTY_1")).trim();
			String tybody = String.valueOf(skuRow.get("__EMPTY_3")).trim();
			String slbody = String.valueOf(skuRow.get("__EMPTY_5")).trim();
			// 确保第四行存在且数据长度至少为11
			if (map.get(4).size() < 11) {
				return AjaxResult.failed(MessageUtils.message("表格数据错误"));
			}
			// 修改后的检查逻辑（使用contains和equals混合）
			if (!khHeader.contains("客户") ||
					!rqHeader.contains("日期") ||
					!ddbody.contains("订单号") ||
					!"TY件号".equals(tybody) ||
					!"数量".equals(slbody)) {
				return AjaxResult.failed(MessageUtils.message("导入模版错误，请检查模版格式"));
			}
			if (map.size() >= 2) {
				Map<String, Object> lastRow = map.get(map.size() - 1);
				String zbHeader = String.valueOf(lastRow.get("__EMPTY")).trim();
				Map<String, Object> secondLastRow = map.get(map.size() - 2);
				String zxsHeader = String.valueOf(secondLastRow.get("__EMPTY")).trim();

				if (zbHeader.contains("制表") && zxsHeader.contains("总箱数")) {
					map = map.subList(0, map.size() - 2);
				}
			}
		} catch (Exception e) {
			// 捕获所有异常并返回错误信息
			return AjaxResult.failed(MessageUtils.message("导入模版错误，请检查模版格式"));
		}


		Set<String> billNoSet = new HashSet<>();
		List<SaleOutStockDetail> detailList = new ArrayList<>();
		String lastBoxNo = null;
		//前期校验excel模板数据
		Boolean aBoolean = checkSaleAOutOrder(userName, user_id, map);
		if (!aBoolean){
			throw new RuntimeException("模板数据校验未通过,请查看传单日志查看具体信息");
		}
		//订单同步开始
		String tbbillNo = syncOrderService.startSyncOrder(userName,user_id,"销售发货明细表AZO订单");
		for (int i = 4; i < map.size(); i++) {
			Map<String, Object> row = map.get(i);
			String detailBillNo = row.getOrDefault("__EMPTY_1", "").toString().trim();//订单号
			if (detailBillNo.isEmpty()) {
				// 可选：记录错误或跳过空订单号的行
				break;
			}
			// 记录唯一订单号
			billNoSet.add(detailBillNo);
			// 处理明细数据
			SaleOutStockDetail detail = new SaleOutStockDetail();
			detail.setBillNo(detailBillNo);
			// 处理合并单元格逻辑（C列箱号）
			if (row.containsKey("__EMPTY")) {
				String currentBoxNo = row.get("__EMPTY").toString().trim();
				if (!currentBoxNo.isEmpty()) {
					lastBoxNo = currentBoxNo; // 更新箱号
				}
			}
			// 继承上一个非空箱号
			detail.setBoxNo(lastBoxNo != null ? lastBoxNo : "");
			if (row.containsKey("__EMPTY_2")) detail.setCustNumber(row.get("__EMPTY_2").toString()); //客户件号
			if (row.containsKey("__EMPTY_3")) detail.setTYNumber(row.get("__EMPTY_3").toString()); // TY件号
			if (row.containsKey("__EMPTY_4")) detail.setSKU(row.get("__EMPTY_4").toString()); //SKU

			if (row.containsKey("__EMPTY_5"))
				detail.setCount(Double.parseDouble(row.get("__EMPTY_5").toString())); //数量


			if (row.containsKey("__EMPTY_6")) detail.setPalletsNumber(row.get("__EMPTY_6").toString()); //拖数
			if (row.containsKey("__EMPTY_7"))
				detail.setNetWeight(Double.parseDouble(row.get("__EMPTY_7").toString())); //净重

			if (row.containsKey("__EMPTY_9")) {
				String valueStr = row.get("__EMPTY_9").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setGrossWeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setGrossWeight(0.0); // 解析失败时设置默认值
				}
			}//毛重

			if (row.containsKey("__EMPTY_11")) {
				String valueStr = row.get("__EMPTY_11").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setLongth(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setLongth(0.0); // 解析失败时设置默认值
				}
			}//长
			if (row.containsKey("__EMPTY_13")) {
				String valueStr = row.get("__EMPTY_13").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setWidth(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setWidth(0.0); // 解析失败时设置默认值
				}
			}//宽
			if (row.containsKey("__EMPTY_15")) {
				String valueStr = row.get("__EMPTY_15").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setHeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setHeight(0.0); // 解析失败时设置默认值
				}
			}//高
			detailList.add(detail);
		}
		// 2. 动态生成主表记录（每个BillNo一个主表）
		List<SaleOutStock> mainList = new ArrayList<>();
		Map<String, Object> headerRow = map.get(1); // 标题行
		for (String billNo : billNoSet) {
			SaleOutStock saleOutStock = new SaleOutStock();
			saleOutStock.setBillNo(billNo);
			System.out.println("Header Row Keys: " + headerRow.keySet());
//			 新增：为 Diffent 字段赋固定值 "天"
			saleOutStock.setDiffent("天"); // 调用 setDiffent() 方法日期
            if (headerRow.containsKey("__EMPTY_10")) {
                Object dateValue = headerRow.get("__EMPTY_10");

                if (dateValue instanceof Number) {
                    double excelDateValue = ((Number) dateValue).doubleValue();
                    Date date = convertExcelDateToJavaDate(excelDateValue);
                    // 清除时间部分
                    date = removeTimeFromDate(date);
                    saleOutStock.setIsDate(date);
                } else if (dateValue instanceof String) {
                    try {
                        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d");
                        Date date = dateFormat.parse(dateValue.toString());
                        // 清除时间部分（虽然解析后可能已为零点，但确保一致）
                        date = removeTimeFromDate(date);
                        saleOutStock.setIsDate(date);
                    } catch (ParseException e) {
                        System.err.println("日期解析失败: " + dateValue);
                    }
                } else {
                    System.err.println("未知的日期格式: " + dateValue);
                }
            }
			// 提取客户编号（H列）
			if (headerRow.containsKey("__EMPTY_1")) {
				String custNo = headerRow.get("__EMPTY_1").toString().replace("客户：", "").trim();
				if (custNo.isEmpty()) {
					return AjaxResult.failed("客户编号为空");
				}
				saleOutStock.setCustNo(custNo);
			}
			//柜号（H列）
			if (headerRow.containsKey("__EMPTY_5")) {
				String boxNo = headerRow.get("__EMPTY_5").toString().replace("柜号：", "").trim();
				if (boxNo.isEmpty()) {
					return AjaxResult.failed("柜号为空");
				}
				saleOutStock.setBoxNo(boxNo);
			}


			mainList.add(saleOutStock);
		}
		List<SyncOrderDetail> orderDetailList = new ArrayList<>();//需要保存到传单日志详情表中的数据
		Map<String, SaleOutStock> mainMap = mainList.stream()
				.collect(Collectors.toMap(SaleOutStock::getBillNo, Function.identity()));

		Map<String, List<SaleOutStockDetail>> detailMap = detailList.stream()
				.collect(Collectors.groupingBy(SaleOutStockDetail::getBillNo));

		for (String billNo : billNoSet) {
			SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
			syncOrderDetail.setOrderNo(billNo);
			syncOrderDetail.setBillNo(tbbillNo);
			syncOrderDetail.setCreateTime(new Date());
			syncOrderDetail.setUpdateTime(new Date());

			try {
				// ===== 核心逻辑优化 =====
				// 1. 查询主表是否已存在
				SaleOutStock main = saleOutStockService.lambdaQuery()
						.eq(SaleOutStock::getBillNo, billNo)
						.one();

				// 2. 获取当前订单的明细数据
				List<SaleOutStockDetail> currentDetails = detailMap.get(billNo);

				if (main != null) {
					// --- 场景1: 主表存在 ---
					// 为明细设置主表ID
					currentDetails.forEach(detail -> detail.setSaleOutStockId(main.getId()));

					// 保存新增明细并记录ID
					saleOutStockDetailService.saveBatch(currentDetails);
					List<Long> newDetailIds = currentDetails.stream()
							.map(SaleOutStockDetail::getId)
							.collect(Collectors.toList());

					try {
						// 同步金蝶
						syncKingdeeOrderService.syncSaleOutOrder(main, currentDetails, user_id);
						syncOrderDetail.setIsSuccess(true);
					} catch (Exception e) {
						// 同步失败：仅删除新增的明细
						if (!newDetailIds.isEmpty()) {
							saleOutStockDetailService.removeByIds(newDetailIds);
						}
						throw new RuntimeException("订单同步失败: " + e.getMessage());
					}
				} else {
					// --- 场景2: 主表不存在 ---
					// 创建主表记录
					SaleOutStock newMain = mainMap.get(billNo);
					saleOutStockService.save(newMain);

					// 为明细设置主表ID
					currentDetails.forEach(detail -> detail.setSaleOutStockId(newMain.getId()));
					saleOutStockDetailService.saveBatch(currentDetails);

					try {
						// 同步金蝶
						syncKingdeeOrderService.syncSaleOutOrder(newMain, currentDetails, user_id);
						syncOrderDetail.setIsSuccess(true);
					} catch (Exception e) {
						// 同步失败：删除整个订单（主表+明细）
						List<Long> detailIds = currentDetails.stream()
								.map(SaleOutStockDetail::getId)
								.collect(Collectors.toList());
						if (!detailIds.isEmpty()) {
							saleOutStockDetailService.removeByIds(detailIds);
						}
						saleOutStockService.removeById(newMain.getId());
						throw new RuntimeException("订单创建失败: " + e.getMessage());
					}
				}
				// ===== 核心逻辑结束 =====
			} catch (Exception e) {
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage(e.getMessage().length() > 500 ?
						e.getMessage().substring(0, 500) : e.getMessage());
			} finally {
				orderDetailList.add(syncOrderDetail);
			}
		}

		Map<String, Object> data = syncOrderService.endSyncOrder(orderDetailList, tbbillNo);
		return AjaxResult.success(data);
	}
	//删除订单
	private void deleteSaleOutStock (SaleOutStock saleOutStock, List<SaleOutStockDetail> saleOutStockDetailList) {
		List<Long> detailIdList = new ArrayList<>();

		for (SaleOutStockDetail detail : saleOutStockDetailList){
			Long id = detail.getId();
			if (!detailIdList.contains(id)){
				detailIdList.add(id);
			}
		}
		saleOutStockService.removeById(saleOutStock.getId());
		saleOutStockDetailService.removeBatchByIds(detailIdList);
}
	/**
	 * 保存销售出库的信息
	 * @param
	 * @param
	 * @return
	 */
	private Boolean saveSaleOutDetail(SaleOutStock saleOutStock,List<SaleOutStockDetail> saledetailList ){

		boolean saveBatch = saleOutStockService.save(saleOutStock);
		boolean detailBatch = saleOutStockDetailService.saveOrUpdateBatch(saledetailList);
		return saveBatch && detailBatch;
	}
		/**
         * 导入发货明细FORD明细
         */
	@Override
	public AjaxResult<Object> importFdData(String userName,Long user_id,List<Map<String, Object>> map) throws Exception{
		if (map == null || map.size()==0){ return AjaxResult.failed(MessageUtils.message("没有获取到数据，请检查模板sheet页"));}

// 1. 提取所有明细中的订单号（假设订单号。在列O，对应 __EMPTY_15）
		// 获取第二行的列头信息（索引为1）
		try {
			Map<String, Object> headRow = map.get(1);
			String khHeader = String.valueOf(headRow.get("__EMPTY")).trim();
			String rqHeader = String.valueOf(headRow.get("__EMPTY_9")).trim();
			Map<String, Object> skuRow = map.get(2);
			String ddbody = String.valueOf(skuRow.get("__EMPTY_1")).trim();
			String tybody = String.valueOf(skuRow.get("__EMPTY_2")).trim();
			String slbody = String.valueOf(skuRow.get("__EMPTY_5")).trim();
			// 确保第四行存在且数据长度至少为11
			if (map.get(4).size() < 11) {
				return AjaxResult.failed(MessageUtils.message("表格数据错误"));
			}
			// 修改后的检查逻辑（使用contains和equals混合）
			if (!khHeader.contains("客户") ||
					!rqHeader.contains("日期") ||
					!ddbody.contains("订单号") ||
					!"TY件号".equals(tybody) ||
					!"数量".equals(slbody)) {
				return AjaxResult.failed(MessageUtils.message("导入模版错误，请检查模版格式"));
			}
			if (map.size() >= 2) {
				Map<String, Object> lastRow = map.get(map.size() - 1);
				String zbHeader = String.valueOf(lastRow.get("__EMPTY")).trim();
				Map<String, Object> secondLastRow = map.get(map.size() - 2);
				String zxsHeader = String.valueOf(secondLastRow.get("__EMPTY")).trim();

				if (zbHeader.contains("制表") && zxsHeader.contains("总箱数")) {
					map = map.subList(0, map.size() - 2);
				}
			}
		} catch (Exception e) {
			// 捕获所有异常并返回错误信息
			return AjaxResult.failed(MessageUtils.message("导入模版错误，请检查模版格式"));
		}
// 1. 提取所有明细中的订单号（假设订单号在列O，对应 __EMPTY_15）
		Set<String> billNoSet = new HashSet<>();
		List<SaleOutStockDetail> detailList = new ArrayList<>();
		//前期校验excel模板数据
		Boolean aBoolean = checkSaleOutOrder(userName, user_id, map);
		if (!aBoolean){
			throw new RuntimeException("模板数据校验未通过,请查看传单日志查看具体信息");
		}
		//订单同步开始
		String tbbillNo = syncOrderService.startSyncOrder(userName,user_id,"销售发货明细表FORD订单");
		String lastBoxNo = null;
		for (int i = 4; i < map.size(); i++) {
			Map<String, Object> row = map.get(i);
			String detailBillNo = row.getOrDefault("__EMPTY_1", "").toString().trim();
			if (detailBillNo.isEmpty()) {
				// 可选：记录错误或跳过空订单号的行
				break;
			}
			// 记录唯一订单号
			billNoSet.add(detailBillNo);
			// 处理明细数据
			SaleOutStockDetail detail = new SaleOutStockDetail();
			detail.setBillNo(detailBillNo);
			// 处理合并单元格逻辑（C列箱号）
			if (row.containsKey("__EMPTY")) {
				String currentBoxNo = row.get("__EMPTY").toString().trim();
				if (!currentBoxNo.isEmpty()) {
					lastBoxNo = currentBoxNo; // 更新箱号
				}
			}
			// 继承上一个非空箱号
			detail.setBoxNo(lastBoxNo != null ? lastBoxNo : "");

			if (row.containsKey("__EMPTY_2")) detail.setTYNumber(row.get("__EMPTY_2").toString()); // TY件号
			if (row.containsKey("__EMPTY_3")) detail.setCustNumber(row.get("__EMPTY_3").toString()); //客户件号

			if (row.containsKey("__EMPTY_4")) detail.setEngerNumber(row.get("__EMPTY_4").toString()); // 工程件号

			if (row.containsKey("__EMPTY_5"))
				detail.setCount(Double.parseDouble(row.get("__EMPTY_5").toString())); //数量


			if (row.containsKey("__EMPTY_6")) {
				String valueStr = row.get("__EMPTY_6").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setSingleWeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setSingleWeight(0.0); // 解析失败时设置默认值
				}
			}//单重
			if (row.containsKey("__EMPTY_7"))
				detail.setNetWeight(Double.parseDouble(row.get("__EMPTY_7").toString())); //净重

			if (row.containsKey("__EMPTY_9")) {
				String valueStr = row.get("__EMPTY_9").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setGrossWeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setGrossWeight(0.0); // 解析失败时设置默认值
				}
			}//毛重

			if (row.containsKey("__EMPTY_11")) {
				String valueStr = row.get("__EMPTY_11").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setLongth(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setLongth(0.0); // 解析失败时设置默认值
				}
			}//长
			if (row.containsKey("__EMPTY_13")) {
				String valueStr = row.get("__EMPTY_13").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setWidth(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setWidth(0.0); // 解析失败时设置默认值
				}
			}//宽
			if (row.containsKey("__EMPTY_15")) {
				String valueStr = row.get("__EMPTY_15").toString();
				try {
					// 直接解析字符串为BigDecimal，避免double转换的精度损失
					BigDecimal bd = new BigDecimal(valueStr);
					// 四舍五入保留两位小数
					bd = bd.setScale(2, RoundingMode.HALF_UP);
					detail.setHeight(bd.doubleValue());
				} catch (NumberFormatException e) {
					detail.setHeight(0.0); // 解析失败时设置默认值
				}
			}//高



			detailList.add(detail);
		}

		// 2. 动态生成主表记录（每个BillNo一个主表）
		List<SaleOutStock> mainList = new ArrayList<>();
		Map<String, Object> headerRow = map.get(1); // 标题行
		for (String billNo : billNoSet) {
			SaleOutStock saleOutStock = new SaleOutStock();
			saleOutStock.setBillNo(billNo);
			System.out.println("Header Row Keys: " + headerRow.keySet());
			// 新增：为 Diffent 字段赋固定值 "天"
			saleOutStock.setDiffent("天"); // 调用 setDiffent() 方法
			// 提取客户编号（H列）
			if (headerRow.containsKey("__EMPTY_1")) {
				String custNo = headerRow.get("__EMPTY_1").toString().replace("柜号：", "").trim();
				if (custNo.isEmpty()) {
					return AjaxResult.failed("客户编号为空");
				}
				saleOutStock.setCustNo(custNo);
			}
			//柜号（H列）
			if (headerRow.containsKey("__EMPTY_5")) {
				String boxNo = headerRow.get("__EMPTY_5").toString().replace("柜号：", "").trim();
				if (boxNo.isEmpty()) {
					return AjaxResult.failed("柜号为空");
				}
				saleOutStock.setBoxNo(boxNo);
			}
			if (headerRow.containsKey("__EMPTY_10")) {
				Object dateValue = headerRow.get("__EMPTY_10");

				if (dateValue instanceof Number) {
					double excelDateValue = ((Number) dateValue).doubleValue();
					Date date = convertExcelDateToJavaDate(excelDateValue);
					// 清除时间部分
					date = removeTimeFromDate(date);
					saleOutStock.setIsDate(date);
				} else if (dateValue instanceof String) {
					try {
						SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/M/d");
						Date date = dateFormat.parse(dateValue.toString());
						// 清除时间部分（虽然解析后可能已为零点，但确保一致）
						date = removeTimeFromDate(date);
						saleOutStock.setIsDate(date);
					} catch (ParseException e) {
						System.err.println("日期解析失败: " + dateValue);
					}
				} else {
					System.err.println("未知的日期格式: " + dateValue);
				}
			}
			mainList.add(saleOutStock);
		}
		List<SyncOrderDetail> orderDetailList = new ArrayList<>();//需要保存到传单日志详情表中的数据
		Map<String, SaleOutStock> mainMap = mainList.stream()
				.collect(Collectors.toMap(SaleOutStock::getBillNo, Function.identity()));

		Map<String, List<SaleOutStockDetail>> detailMap = detailList.stream()
				.collect(Collectors.groupingBy(SaleOutStockDetail::getBillNo));

		for (String billNo : billNoSet) {
			SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
			syncOrderDetail.setOrderNo(billNo);
			syncOrderDetail.setBillNo(tbbillNo);
			syncOrderDetail.setCreateTime(new Date());
			syncOrderDetail.setUpdateTime(new Date());

			try {
				// ===== 核心逻辑优化 =====
				// 1. 查询主表是否已存在
				SaleOutStock main = saleOutStockService.lambdaQuery()
						.eq(SaleOutStock::getBillNo, billNo)
						.one();

				// 2. 获取当前订单的明细数据
				List<SaleOutStockDetail> currentDetails = detailMap.get(billNo);

				if (main != null) {
					// --- 场景1: 主表存在 ---
					// 为明细设置主表ID
					currentDetails.forEach(detail -> detail.setSaleOutStockId(main.getId()));

					// 保存新增明细并记录ID
					saleOutStockDetailService.saveBatch(currentDetails);
					List<Long> newDetailIds = currentDetails.stream()
							.map(SaleOutStockDetail::getId)
							.collect(Collectors.toList());

					try {
						// 同步金蝶
						syncKingdeeOrderService.syncSaleOutOrder(main, currentDetails, user_id);
						syncOrderDetail.setIsSuccess(true);
					} catch (Exception e) {
						// 同步失败：仅删除新增的明细
						if (!newDetailIds.isEmpty()) {
							saleOutStockDetailService.removeByIds(newDetailIds);
						}
						throw new RuntimeException("订单同步失败: " + e.getMessage());
					}
				} else {
					// --- 场景2: 主表不存在 ---
					// 创建主表记录
					SaleOutStock newMain = mainMap.get(billNo);
					saleOutStockService.save(newMain);

					// 为明细设置主表ID
					currentDetails.forEach(detail -> detail.setSaleOutStockId(newMain.getId()));
					saleOutStockDetailService.saveBatch(currentDetails);

					try {
						// 同步金蝶
						syncKingdeeOrderService.syncSaleOutOrder(newMain, currentDetails, user_id);
						syncOrderDetail.setIsSuccess(true);
					} catch (Exception e) {
						// 同步失败：删除整个订单（主表+明细）
						List<Long> detailIds = currentDetails.stream()
								.map(SaleOutStockDetail::getId)
								.collect(Collectors.toList());
						if (!detailIds.isEmpty()) {
							saleOutStockDetailService.removeByIds(detailIds);
						}
						saleOutStockService.removeById(newMain.getId());
						throw new RuntimeException("订单创建失败: " + e.getMessage());
					}
				}
				// ===== 核心逻辑结束 =====
			} catch (Exception e) {
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage(e.getMessage().length() > 500 ?
						e.getMessage().substring(0, 500) : e.getMessage());
			} finally {
				orderDetailList.add(syncOrderDetail);
			}
		}

		Map<String, Object> data = syncOrderService.endSyncOrder(orderDetailList, tbbillNo);
		return AjaxResult.success(data);
	}
	/**
	 * 校验销售销售出库单导入的数据
	 * @param user_id
	 * @param map
	 * @return
	 * @throws Exception
	 */
	private Boolean checkSaleOutOrder(String userName,Long user_id,List<Map<String,Object>> map) throws Exception{
		//添加行号
		int i = 4;
		for (Map<String,Object> data : map){
			data.put("line",i);
			i++;
		}
		//添加之前做一个删除
		materialService.deleteSaleOutOrder(userName,user_id);

		//sqlserver数据库添加当前导入的数据
		materialService.saveSaleOutOrder(userName,user_id,map);
		//校验客户订单号
		List<Map<String,Object>> checkCusBill =  materialService.checkCusBillNoout(user_id);
		//校验物料
		List<Map<String,Object>> checkMaterial =  materialService.checkMaterialout(user_id);
		//校验客户（不为空）
		List<Map<String,Object>> checkCustomer =  materialService.checkCustomerout(user_id);
		//校验数量是否都大于0
		List<Map<String,Object>> checkCount =  materialService.checkCountout(user_id);
		//校验日期
		List<Map<String,Object>> checkIsTime =  materialService.checkIsTime(user_id);
		//判断查询的数据如果都为空的话说明模板数据校验通过可以导入,如果不为空的话添加日志信息并且停止传单
		if (VtuzxUtil.isEmpty(checkCusBill) &&  VtuzxUtil.isEmpty(checkMaterial) && VtuzxUtil.isEmpty(checkCustomer) && VtuzxUtil.isEmpty(checkCount) &&  VtuzxUtil.isEmpty(checkIsTime)){
			return true;
		}  else {//有一个不等于空的就说明有问题,需要向日志中添加信息
			saveOrderLog(userName,user_id,checkCusBill,checkMaterial,checkCustomer,checkCount,checkIsTime);
			return false;
		}

	}

	private Boolean checkSaleAOutOrder(String userName,Long user_id,List<Map<String,Object>> map) throws Exception{
		//添加行号
		int i = 4;
		for (Map<String,Object> data : map){
			data.put("line",i);
			i++;
		}
		//添加之前做一个删除
		materialService.deleteSaleOutOrder(userName,user_id);

		materialService.saveSaleAOutOrder(userName,user_id,map);
		//校验客户订单号
		List<Map<String,Object>> checkCusBill =  materialService.checkCusBillNoout(user_id);
		//校验物料
		List<Map<String,Object>> checkMaterial =  materialService.checkMaterialout(user_id);
		//校验客户（不为空）
		List<Map<String,Object>> checkCustomer =  materialService.checkCustomerout(user_id);
		//校验数量是否都大于0
		List<Map<String,Object>> checkCount =  materialService.checkCountout(user_id);
		//校验日期
		List<Map<String,Object>> checkIsTime =  materialService.checkIsTime(user_id);
		//判断查询的数据如果都为空的话说明模板数据校验通过可以导入,如果不为空的话添加日志信息并且停止传单
		if (VtuzxUtil.isEmpty(checkCusBill) &&  VtuzxUtil.isEmpty(checkMaterial) && VtuzxUtil.isEmpty(checkCustomer) && VtuzxUtil.isEmpty(checkCount) &&  VtuzxUtil.isEmpty(checkIsTime)){
			return true;
		}  else {//有一个不等于空的就说明有问题,需要向日志中添加信息
			saveOrderLog(userName,user_id,checkCusBill,checkMaterial,checkCustomer,checkCount,checkIsTime);
			return false;
		}

	}
	/**
	 * 模板级校验添加日志信息
	 * @param checkCusBill
	 * @param checkMaterial
	 * @param checkCustomer
	 * @param checkCount
	 */
	private void saveOrderLog(String userName,Long user_id,List<Map<String,Object>> checkCusBill,List<Map<String,Object>> checkMaterial,List<Map<String,Object>> checkCustomer,List<Map<String,Object>> checkCount,List<Map<String,Object>> checkIsTime){
		String tbbillNo = syncOrderService.startSyncOrder(userName,user_id,"销售出库单模板数据校验");
		List<SyncOrderDetail> orderDetailList = new ArrayList<>();
		if (!VtuzxUtil.isEmpty(checkCusBill)){//客户订单号校验
			for (Map<String,Object> data : checkCusBill){
				int line = VtuzxUtil.getInt(data,"LINE");//行号
				SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
				syncOrderDetail.setOrderNo("销售出库单模板数据校验");//客户订单号
				syncOrderDetail.setBillNo(tbbillNo);
				syncOrderDetail.setCreateTime(new Date());
				syncOrderDetail.setUpdateTime(new Date());
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage("第" + line + "行的客户订单号不允许为空，或销售订单中不存在该客户订单号,或销售订单未完成审核");
				orderDetailList.add(syncOrderDetail);
			}
		}

		if (!VtuzxUtil.isEmpty(checkMaterial)){//物料校验
			for (Map<String,Object> data : checkMaterial){
				int line = VtuzxUtil.getInt(data,"LINE");//行号
				SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
				syncOrderDetail.setOrderNo("销售出库单模板数据校验");//客户订单号
				syncOrderDetail.setBillNo(tbbillNo);
				syncOrderDetail.setCreateTime(new Date());
				syncOrderDetail.setUpdateTime(new Date());
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage("第" + line + "行的TY件号未审核,或者不存在,或者已禁用,请确认");
				orderDetailList.add(syncOrderDetail);
			}
		}

		if (!VtuzxUtil.isEmpty(checkCustomer)){//客户校验
			for (Map<String,Object> data : checkCustomer){
				int line = VtuzxUtil.getInt(data,"LINE");//行号
				SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
				syncOrderDetail.setOrderNo("销售出库单模板数据校验");//客户订单号
				syncOrderDetail.setBillNo(tbbillNo);
				syncOrderDetail.setCreateTime(new Date());
				syncOrderDetail.setUpdateTime(new Date());
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage("第" + line + "行的客户未审核,或者不存在,或者已禁用,或与销售订单客户不同,请确认");
				orderDetailList.add(syncOrderDetail);
			}
		}

		if (!VtuzxUtil.isEmpty(checkCount)){//数量校验
			for (Map<String,Object> data : checkCount){
				int line = VtuzxUtil.getInt(data,"LINE");//行号
				SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
				syncOrderDetail.setOrderNo("销售出库单模板数据校验");//客户订单号
				syncOrderDetail.setBillNo(tbbillNo);
				syncOrderDetail.setCreateTime(new Date());
				syncOrderDetail.setUpdateTime(new Date());
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage("第" + line + "的数量必须大于0");
				orderDetailList.add(syncOrderDetail);
			}
		}
		if (!VtuzxUtil.isEmpty(checkIsTime)){//时间校验
			for (Map<String,Object> data : checkIsTime){
				int line = VtuzxUtil.getInt(data,"LINE");//行号
				SyncOrderDetail syncOrderDetail = new SyncOrderDetail();
				syncOrderDetail.setOrderNo("销售出库单模板数据校验");//客户订单号
				syncOrderDetail.setBillNo(tbbillNo);
				syncOrderDetail.setCreateTime(new Date());
				syncOrderDetail.setUpdateTime(new Date());
				syncOrderDetail.setIsSuccess(false);
				syncOrderDetail.setMessage("第" + line + "的时间为空，或小于销售订单时间");
				orderDetailList.add(syncOrderDetail);
			}
		}

		syncOrderService.endSyncOrder(orderDetailList,tbbillNo);
	}


	/**
	 * 导出数据
	 */
	@Override  
	public AjaxResult<Object> dumpdata(SaleOutStockRequest request){
      Page<SaleOutStock> page = new Page<SaleOutStock>(request.getPage(), request.getLimit());
	  IPage<SaleOutStock> list =selectList(request, page);
	  String header="编号,确认日期,订单编号,客户编码";
	  Map<String,Object> retMap=new HashMap<String, Object>();
	  retMap.put("header", StringUtils.split(header, ','));
	  retMap.put("filename", "销售出库单.xlsx");
	  retMap.put("percentage", (int)list.getCurrent()*100/list.getPages());
	  retMap.put("data", list.getRecords());
	  return AjaxResult.success(retMap);
	}

	/**
	 * 销售出库明细详情
	 * @param map
	 * @return
	 * @throws Exception
	 */
	@Override
	public Map<String, Object> getSaleOutStockDetail(Map<String, Object> map) {
		String billNo = map.get("billNo").toString();
		SaleOutStock saleoutstockform = saleOutStockDao.selectOne(new LambdaQueryWrapper<SaleOutStock>()
				.eq(SaleOutStock::getBillNo,billNo));
		List<SaleOutStockDetail> saleoutstockList = saleOutStockDetailDao.selectList(new LambdaQueryWrapper<SaleOutStockDetail>()
				.eq(SaleOutStockDetail::getBillNo,billNo));
		Map<String,Object> data = new HashMap<>();
		data.put("data",saleoutstockform);
		data.put("dataList",saleoutstockList);
		return data;
	}


	/**
	 * 销售出库明细删除详情
	 * @param map
	 * @return
	 * @throws Exception
	 */
	@Override
	public Map<String, Object> getSaleOutStockDelete(Map<String, Object> map)throws Exception {
		String billNo = map.get("billNo").toString();
		// 参数校验
		String djFbillno = "";
		VtuzxKingdeeCloudClient client = vtuzxKingdeeService.loginKingdee();
		//根据客户名查询客户编码
		List<VtuzxMap> prdcumQuery = vtuzxKingdeeService.query(client, "SAL_OUTSTOCK", new VtuzxArrayList<>(
						"F_PSUH_Text_83g",
						"FBillNo"
				),
				// 组合两个过滤条件（规格型号 + 物料分组）
				String.format("F_PSUH_Text_83g = '%s' ",
						billNo), null, 0, 0);
		if (!VtuzxUtil.isEmpty(prdcumQuery)) {
			djFbillno = VtuzxUtil.getString(prdcumQuery.get(0),"FBillNo");
			throw new RuntimeException(String.format("该订单已存在不能删除订单号%s 销售出库单号%s ", billNo,djFbillno));
		}
		// 删除本地数据库记录
		int deletedDetails = saleOutStockDetailDao.delete(
				new LambdaQueryWrapper<SaleOutStockDetail>()
						.eq(SaleOutStockDetail::getBillNo, billNo)
		);
		int deletedMain = saleOutStockDao.delete(
				new LambdaQueryWrapper<SaleOutStock>()
						.eq(SaleOutStock::getBillNo, billNo)
		);

		Map<String, Object> data = new HashMap<>();
		data.put("success", true);
		data.put("message", String.format("主表删除 %d 条，明细表删除 %d 条", deletedMain, deletedDetails));
		return data;
	}


    
	
}